package com.watercube.dao.util;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.InnerClass;
import org.mybatis.generator.api.dom.java.InnerEnum;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.internal.util.StringUtility;

import com.watercube.common.util.DateTimeUtil;

public class MyCommentGenerator implements CommentGenerator {

  private String project;
  private String author;
  private String currentDateChinese;
  private CommentHandler commentHandler;
  private boolean suppressAllComments;

  private static String PROJECT = "project";
  private static String AUTHOR = "author";

  public MyCommentGenerator() {
    super();
    suppressAllComments = false;
    project = "watercube";
    author = "yangyh";
    commentHandler = new CommentHandler();
    currentDateChinese = DateTimeUtil.toString(new Date(), DateTimeUtil.FORMAT_YYYYMMDD_CHINESE);
  }

  /**
   * @Description 这个方法用来读取generatorConfig.xml 中的 commentGenerator 的属性 支持自定义
   * @author master-yangyh
   * @date 2017年7月25日
   * @param properties
   * @version V1.0
   * @see org.mybatis.generator.api.CommentGenerator#addConfigurationProperties(java.util.Properties)
   */
  @Override
  public void addConfigurationProperties(Properties properties) {
    suppressAllComments = StringUtility
        .isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));
    project = properties.getProperty(PROJECT);
    author = StringUtils.isBlank(properties.getProperty(AUTHOR)) ? author
        : properties.getProperty(AUTHOR);
  }

  /**
   * @Description 给每个字段添加注释等等
   * @author master-yangyh
   * @date 2017年7月25日
   * @param field
   * @param introspectedTable
   * @param introspectedColumn
   * @version V1.0
   * @see org.mybatis.generator.api.CommentGenerator#addFieldComment(org.mybatis.generator.api.dom.java.Field,
   *      org.mybatis.generator.api.IntrospectedTable, org.mybatis.generator.api.IntrospectedColumn)
   */
  @Override
  public void addFieldComment(Field field, IntrospectedTable introspectedTable,
      IntrospectedColumn introspectedColumn) {
    // 添加注释
    if (introspectedColumn.getRemarks() != null && !introspectedColumn.getRemarks().equals("")) {
      field.addJavaDocLine("// " + introspectedColumn.getRemarks() + " ");
    }

    // 主键添加注解
    List<IntrospectedColumn> list = introspectedTable.getPrimaryKeyColumns();
    for (IntrospectedColumn introspectedColumn2 : list) {
      if (introspectedColumn.getActualColumnName()
          .equals(introspectedColumn2.getActualColumnName())) {
        field.addAnnotation("@Id");
      }
    }
  }

  @Override
  public void addFieldComment(Field field, IntrospectedTable introspectedTable) {

  }

  /**
   * @Project: master-base-dao
   * @Description
   * @author master-yangyh
   * @date 2017年7月25日
   * @version V1.0
   */
  @Override
  public void addModelClassComment(TopLevelClass topLevelClass,
      IntrospectedTable introspectedTable) {

    // 创建导入的import Set
    Set<FullyQualifiedJavaType> set = createImportSet();
    topLevelClass.addImportedTypes(set);

    topLevelClass.addAnnotation("@Table(name = \"client\")");

    // 创建序列化的字段
    Field field = createSeriableField();
    topLevelClass.addField(field);

    addModelClassComment(topLevelClass);
  }

  /**
   * @Description 创建导入的import Set
   * @author master-yangyh
   * @date 2017年7月25日
   * @return
   * @version V1.0
   */
  private Set<FullyQualifiedJavaType> createImportSet() {
    FullyQualifiedJavaType idType = new FullyQualifiedJavaType("javax.persistence.Id");
    FullyQualifiedJavaType tableType = new FullyQualifiedJavaType("javax.persistence.Table");
    Set<FullyQualifiedJavaType> set = new HashSet<>();
    set.add(idType);
    set.add(tableType);
    return set;
  }

  /**
   * @Description 创建序列化的字段
   * @author master-yangyh
   * @date 2017年7月25日
   * @return
   * @version V1.0
   */
  private Field createSeriableField() {
    Field field = new Field();
    field.setFinal(true);
    field.setInitializationString("1L"); //$NON-NLS-1$
    field.setName("serialVersionUID"); //$NON-NLS-1$
    field.setStatic(true);
    field.setType(new FullyQualifiedJavaType("long")); //$NON-NLS-1$
    field.setVisibility(JavaVisibility.PRIVATE);
    return field;
  }

  private void addModelClassComment(TopLevelClass topLevelClass) {
    StringBuilder sb = new StringBuilder();

    sb = commentHandler.getStartComment(sb);
    topLevelClass.addJavaDocLine(sb.toString());

    sb = commentHandler.getProjectcomment(sb);
    topLevelClass.addJavaDocLine(sb.toString());

    sb = commentHandler.getDescriptionComment(sb);
    topLevelClass.addJavaDocLine(sb.toString());

    sb = commentHandler.getAuthorComment(sb);
    topLevelClass.addJavaDocLine(sb.toString());

    sb = commentHandler.getDateComment(sb);
    topLevelClass.addJavaDocLine(sb.toString());

    sb = commentHandler.getVersionComment(sb);
    topLevelClass.addJavaDocLine(sb.toString());

    sb = commentHandler.getEndComment(sb);
    topLevelClass.addJavaDocLine(sb.toString());
  }

  /**
   * @Project: master-base-dao
   * @Description 注解handler
   * @author master-yangyh
   * @date 2017年7月25日
   * @version V1.0
   */
  private class CommentHandler {
    /**
     * @Description 获得结束的注释
     * @author master-yangyh
     * @date 2017年7月25日
     * @param sb
     * @return
     * @version V1.0
     */
    private StringBuilder getEndComment(StringBuilder sb) {
      sb.setLength(0);
      return sb.append(" **/");
    }

    /**
     * @Description 获得版本的注释
     * @author master-yangyh
     * @date 2017年7月25日
     * @param sb
     * @return
     * @version V1.0
     */
    private StringBuilder getVersionComment(StringBuilder sb) {
      sb.setLength(0);
      return sb.append(" * @version V1.0 ");
    }

    /**
     * @Description 获得当前日期的注释
     * @author master-yangyh
     * @date 2017年7月25日
     * @param sb
     * @return
     * @version V1.0
     */
    private StringBuilder getDateComment(StringBuilder sb) {
      sb.setLength(0);
      sb.append(" * @date " + currentDateChinese);
      return sb;
    }

    /**
     * @Description 获得作者的注释
     * @author master-yangyh
     * @date 2017年7月25日
     * @param sb
     * @return
     * @version V1.0
     */
    private StringBuilder getAuthorComment(StringBuilder sb) {
      sb.setLength(0);
      sb.append(" * @author ");
      return sb.append(author);
    }

    /**
     * @Description 获得描述的注释
     * @author master-yangyh
     * @date 2017年7月25日
     * @param sb
     * @return
     * @version V1.0
     */
    private StringBuilder getDescriptionComment(StringBuilder sb) {
      sb.setLength(0);
      return sb.append(" * @Description");
    }

    /**
     * @Description 获得project的注释
     * @author master-yangyh
     * @date 2017年7月25日
     * @param sb
     * @return
     * @version V1.0
     */
    private StringBuilder getProjectcomment(StringBuilder sb) {
      sb.setLength(0);
      sb.append(" * @Project ");
      return sb.append(project);
    }

    /**
     * @Description 获得开始的注解
     * @author master-yangyh
     * @date 2017年7月25日
     * @param sb
     * @version V1.0
     * @return
     */
    private StringBuilder getStartComment(StringBuilder sb) {
      sb.setLength(0);
      return sb.append("/**");
    }

    /**
     * @Description 获得param的注释
     * @author master-yangyh
     * @date 2017年7月25日
     * @param sb
     * @param parm
     * @param introspectedColumn
     * @return
     * @version V1.0
     */
    private StringBuilder getParamComment(StringBuilder sb, Parameter parm,
        IntrospectedColumn introspectedColumn) {
      sb.setLength(0);
      sb.append(" * @param ");
      sb.append(parm.getName());
      sb.append(" ");
      return sb.append(introspectedColumn.getRemarks());
    }

    private StringBuilder getReturnComment(StringBuilder sb,
        IntrospectedColumn introspectedColumn) {
      sb.setLength(0);
      sb.append(" * @return ");
      sb.append(introspectedColumn.getActualColumnName());
      sb.append(" ");
      return sb.append(introspectedColumn.getRemarks());
    }
  }

  @Override
  public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) {
  }

  @Override
  public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable,
      boolean markAsDoNotDelete) {

  }

  @Override
  public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) {

  }

  @Override
  public void addGetterComment(Method method, IntrospectedTable introspectedTable,
      IntrospectedColumn introspectedColumn) {
    if (suppressAllComments) {
      return;
    }

    StringBuilder sb = new StringBuilder();

    method.addJavaDocLine(commentHandler.getStartComment(sb).toString());
    method.addJavaDocLine(commentHandler.getReturnComment(sb, introspectedColumn).toString());
    method.addJavaDocLine(commentHandler.getEndComment(sb).toString());

  }

  @Override
  public void addSetterComment(Method method, IntrospectedTable introspectedTable,
      IntrospectedColumn introspectedColumn) {
    if (suppressAllComments) {
      return;
    }

    StringBuilder sb = new StringBuilder();
    Parameter parm = method.getParameters().get(0);
    method.addJavaDocLine(commentHandler.getStartComment(sb).toString());
    method.addJavaDocLine(commentHandler.getParamComment(sb, parm, introspectedColumn).toString());
    method.addJavaDocLine(commentHandler.getEndComment(sb).toString());

  }

  @Override
  public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {

  }

  @Override
  public void addJavaFileComment(CompilationUnit compilationUnit) {

  }

  @Override
  public void addComment(XmlElement xmlElement) {

  }

  @Override
  public void addRootComment(XmlElement rootElement) {

  }

}